//
// Created by joker on 9/3/19.
//
#pragma once
#ifndef LIBDL_CORE_FUNCTIONAL_UTILS_H
#define LIBDL_CORE_FUNCTIONAL_UTILS_H

#include <TH/TH.h>
#include <ATen/ATen.h>
#include <c10/core/CPUAllocator.h>
//TODO: check if cuda is available


#ifdef CUDA_AVAILABLE
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAFunctions.h>
#include <c10/cuda/CUDACachingAllocator.h>
//#include <ATen/CUDAGenerator.h>
#endif


#ifdef __linux__

#define LD_LINUX

#include <sys/sysinfo.h>

#elif defined(_WIN32)

#define LD_WIN32

#include <Windows.h>

#endif


class functional_utils {
public:

    static double cuda_memory_allocated_ratio() {
#if defined(CUDA_AVAILABLE)
        if(!at::cuda::is_available()){
            return 0;
        }
//     std::cout<<"Memory allocated:"<<c10::cuda::CUDACachingAllocator::currentMemoryAllocated(0)<<std::endl;
//     std::cout<<"Memory cached:"<<c10::cuda::CUDACachingAllocator::currentMemoryCached(0)<<std::endl;
//     std::cout<<"MAXMemory allocated:"<<c10::cuda::CUDACachingAllocator::maxMemoryAllocated(0)<<std::endl;
//     std::cout<<"MAXMemory cached:"<<c10::cuda::CUDACachingAllocator::maxMemoryCached(0)<<std::endl;
        size_t free, all;
        cudaMemGetInfo(&free, &all);
        size_t cached = c10::cuda::CUDACachingAllocator::maxMemoryCached(at::cuda::current_device());

//    std::cout << "Now(" << c10::cuda::CUDACachingAllocator::currentMemoryAllocated(0) << "/" << (free + cached) << ")"
//              << std::endl;
        return (double) c10::cuda::CUDACachingAllocator::currentMemoryAllocated(0) / (free + cached);
#else
        return 0;
#endif
    }

    static double cpu_memory_allocated_ratio();


};


#endif //LIBDL_CORE_FUNCTIONAL_UTILS_H
